package com.bestv.search.spider.youku.sync;

import com.bestv.search.spider.model.VideoBaseInfo;
import com.bestv.search.spider.service.VideoBaseInfoManager;
import com.bestv.search.spider.util.SpiderConst;
import com.bestv.search.spider.util.SpiderUtil;
import com.bestv.search.spider.util.StringUtil;
import com.bestv.search.spider.youku.model.YouKuVideoDetailInfo;
import com.bestv.search.spider.youku.service.YouKuVideoDetailInfoManager;
import com.bestv.search.spider.youku.util.YouKuAppKeyPool;
import com.bestv.search.spider.youku.util.YouKuUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class YouKuHotCommentsSyncer extends QuartzJobBean {

    private static boolean isRunning = false;
    private final Log log = LogFactory.getLog(YouKuHotCommentsSyncer.class);
    private VideoBaseInfoManager infoManager;
    private YouKuVideoDetailInfoManager youKuVideoDetailInfoManager;
    private String infoFolder;

    private static String getVideoIdByPlay_Link(String play_link) {
        if (play_link != null && !play_link.equals(SpiderConst.EMPTY)) {
            return play_link.substring(play_link.lastIndexOf(SpiderConst.UNDER_LINE) + 1,
                    play_link.lastIndexOf(SpiderConst.POINT));
        }
        return null;
    }

    @Override
    protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {
        if (!isRunning) {
            isRunning = true;
            // Start sync time
            Calendar c = Calendar.getInstance();
            String fileFolderPath = getCommentsFileFolderByDateTime(c.getTime());

            // remove over 7 days' files.
            String parentFolder = fileFolderPath + File.separator + SpiderConst.POINT + SpiderConst.POINT
                    + File.separator;
            String[] overdueFolders = SpiderUtil.getOver7DaysFolders(parentFolder);
            if (overdueFolders != null) {
                for (String path : overdueFolders) {
                    SpiderUtil.deleteDirectory(parentFolder + path);
                }
            }

            String isRunningFile = fileFolderPath + File.separator + SpiderConst.ISRUNNING_FLAG_FILE;
            SpiderUtil.createFile(isRunningFile);

            log.info("Start sync videos's hot comments from YouKu @" + new Date());
            String file = fileFolderPath + File.separator + SpiderConst.YOUKU_ALL_VIDEOS_COMMENTS_FILE;

            boolean syncFinished = false;
            do {
                if (!YouKuAppKeyPool.isBusy) {
                    syncFinished = syncHotComments(file, c.getTime());
                } else {
                    try {
                        Thread.sleep(SpiderConst.THREAD_CHECK_INTERVAL_SECOND * 1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            } while (!syncFinished);

            SpiderUtil.deleteFile(isRunningFile);

            isRunning = false;
            log.info("Sync videos's hot comments from YouKu end @" + new Date());
        } else {
            log.info("Last video hot comments sync process is still running");
        }
    }

    /**
     * @param fileFolder
     * @param syncTime
     * @return Whether sync finished
     */
    private boolean syncHotComments(String fileFolder, Date syncTime) {
        List<YouKuVideoDetailInfo> infos = youKuVideoDetailInfoManager.getInfoForHotComments(syncTime);
        List<VideoBaseInfo> commentsSyncedList = new ArrayList<VideoBaseInfo>();

        if (infos == null || infos.size() == 0) {
            // Comments has sync end.
            return true;
        } else {
            try {
                for (YouKuVideoDetailInfo info : infos) {
                    StringBuffer comments = new StringBuffer();
                    if (!YouKuAppKeyPool.isBusy) {
                        // No play link that says no video at now, so don't have
                        // hot comments
                        if (info.getPlay_link() != null && !info.getPlay_link().equals(SpiderConst.EMPTY)) {
                            String video_Id = getVideoIdByPlay_Link(info.getPlay_link());
                            int pageIndex = 1;
                            int pageSize = 0;
                            boolean syncFinished = false;
                            do {
                                String url = StringUtil.buildBuffer(
                                        new String[]{SpiderConst.YOUKU_HOT_COMMENTS_URL, SpiderConst.VIDEO_ID,
                                                SpiderConst.EQUAL_FLAG, video_Id, SpiderConst.URL_SPLIT_FLAG,
                                                SpiderConst.PAGE, SpiderConst.EQUAL_FLAG, String.valueOf(pageIndex),
                                                SpiderConst.URL_SPLIT_FLAG, SpiderConst.COUNT, SpiderConst.EQUAL_FLAG,
                                                String.valueOf(SpiderConst.YOUKU_COMMENTS_PAGE_COUNT)}).toString();
                                String response = null;
                                if (!YouKuAppKeyPool.isBusy) {

                                    response = new YouKuUtil().sendRequestByAppKey(url);
                                    // Handle response
                                    if (response != null && !response.equalsIgnoreCase(SpiderConst.EMPTY)) {
                                        String nativeStr = StringUtil.ascii2Native(response);
                                        if (comments.length() == 0) {
                                            String totalStr = nativeStr.substring(0,
                                                    nativeStr.indexOf(SpiderConst.COMMA)).split(SpiderConst.COLON)[1];
                                            // replace left \" and right \"
                                            totalStr = totalStr.replace(SpiderConst.DOUBLE_QUOTATION_MARKS,
                                                    SpiderConst.EMPTY);
                                            totalStr = totalStr.replace(SpiderConst.DOUBLE_QUOTATION_MARKS,
                                                    SpiderConst.EMPTY);

                                            // Convert it to Integer
                                            int total = Integer
                                                    .valueOf(totalStr.trim().equals(SpiderConst.EMPTY)
                                                            || totalStr.trim().equals(SpiderConst.NULL) ? "0"
                                                            : totalStr.trim());
                                            if (total == 0) {
                                                syncFinished = true;
                                                break;
                                            }
                                            pageSize = total / SpiderConst.YOUKU_COMMENTS_PAGE_COUNT;
                                            if (total % SpiderConst.YOUKU_COMMENTS_PAGE_COUNT != 0) {
                                                pageSize = pageSize + 1;
                                            }

                                            comments = StringUtil.buildBuffer(new String[]{
                                                    nativeStr.substring(0, nativeStr.indexOf(SpiderConst.COMMA) + 1),
                                                    SpiderConst.DOUBLE_QUOTATION_MARKS, SpiderConst.ID,
                                                    SpiderConst.DOUBLE_QUOTATION_MARKS, SpiderConst.COLON,
                                                    SpiderConst.DOUBLE_QUOTATION_MARKS, info.getId(),
                                                    SpiderConst.DOUBLE_QUOTATION_MARKS, SpiderConst.COMMA,
                                                    SpiderConst.DOUBLE_QUOTATION_MARKS, SpiderConst.NAME,
                                                    SpiderConst.DOUBLE_QUOTATION_MARKS, SpiderConst.COLON,
                                                    SpiderConst.DOUBLE_QUOTATION_MARKS, info.getName(),
                                                    SpiderConst.DOUBLE_QUOTATION_MARKS,
                                                    nativeStr.substring(nativeStr.indexOf(SpiderConst.COMMENTS) - 2)});
                                        } else {
                                            comments.insert(comments.length() - 2, SpiderConst.COMMA);
                                            comments.insert(comments.length() - 2, nativeStr.substring(
                                                    nativeStr.indexOf(SpiderConst.COMMENTS) + 11,
                                                    nativeStr.length() - 2));

                                        }
                                    } else {
                                        // YouKuAppKeyPool is busy, end this
                                        // times sync.
                                        if (YouKuAppKeyPool.isBusy) {
                                            syncFinished = false;
                                            break;
                                        } else {
                                            // Don't have hot comments for this
                                            // video, ignore it.
                                            syncFinished = true;
                                            break;
                                        }
                                    }
                                } else {
                                    syncFinished = false;
                                    break;
                                }
                                if (pageIndex == pageSize) {
                                    syncFinished = true;
                                }
                                pageIndex++;
                            } while (pageIndex <= pageSize);

                            if (syncFinished) {
                                info.setHotcommentsSyncTime(syncTime);
                                commentsSyncedList.add(info);
                            }

                            if (commentsSyncedList.size() > 100) {
                                infoManager.saveOrUpdate(commentsSyncedList);
                                commentsSyncedList = new ArrayList<VideoBaseInfo>();
                            }

                            // write comments to file.
                            YouKuUtil.addTextToFile(comments.toString(), fileFolder);
                        } else {
                            info.setHotcommentsSyncTime(syncTime);
                            commentsSyncedList.add(info);
                        }
                    } else {
                        // end this time's sync
                        break;
                    }
                }
            } finally {
                // Always make sure update commentsSyncedList to DB.
                infoManager.saveOrUpdate(commentsSyncedList);
            }
        }

        // Checks comments whether is sync finished.
        infos = youKuVideoDetailInfoManager.getInfoForHotComments(syncTime);
        if (infos == null || infos.size() == 0) {
            // Comments has sync end.
            return true;
        }

        return false;
    }

    private String getCommentsFileFolderByDateTime(Date date) {
        String commentsFolder = this.getInfoFolder() + File.separator + SpiderConst.COMMENTS;
        File folder = new File(commentsFolder);
        if (!folder.exists()) {
            folder.mkdir();
        }

        commentsFolder = commentsFolder + File.separator + SpiderConst.YOUKU;
        folder = new File(commentsFolder);
        if (!folder.exists()) {
            folder.mkdir();
        }

        SimpleDateFormat format = new SimpleDateFormat(SpiderConst.DATETIME_FORMAT);
        String dateTimeFolder = commentsFolder + File.separator + format.format(date);
        folder = new File(dateTimeFolder);
        if (!folder.exists()) {
            folder.mkdir();
        }

        return dateTimeFolder;
    }

    public VideoBaseInfoManager getInfoManager() {
        return infoManager;
    }

    public void setInfoManager(VideoBaseInfoManager infoManager) {
        this.infoManager = infoManager;
    }

    public YouKuVideoDetailInfoManager getYouKuVideoDetailInfoManager() {
        return youKuVideoDetailInfoManager;
    }

    public void setYouKuVideoDetailInfoManager(YouKuVideoDetailInfoManager youKuVideoDetailInfoManager) {
        this.youKuVideoDetailInfoManager = youKuVideoDetailInfoManager;
    }

    public String getInfoFolder() {
        return infoFolder;
    }

    public void setInfoFolder(String infoFolder) {
        this.infoFolder = infoFolder;
    }
}
